﻿// <copyright file="StringParser.cs" company="Codeplex project Eco.Contrib"> 
// The MIT License (MIT) 
// </copyright> 
// <author>Peter Buchmann</author> 

namespace Eco.Contrib
{
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// StringParser: parses a string
    /// </summary>
    internal class StringParser
    {
        /// <summary>
        /// CharList: List of chars
        /// </summary>
        private List<CharWithPosition> charList = null;

        /// <summary>
        /// Initializes a new instance of the <see cref="StringParser"/> class.
        /// </summary>
        /// <param name="text">The text.</param>
        public StringParser(string text)
        {
            this.Text = text;
            this.charList = new List<CharWithPosition>();
            this.Pos = 0;
            this.Line = 0;
            this.Col = 0;
        }

        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        /// <value>
        /// The text.
        /// </value>
        private string Text { get; set; }

        /// <summary>
        /// Gets or sets the pos.
        /// </summary>
        /// <value>
        /// The pos.
        /// </value>
        private int Pos { get; set; }

        /// <summary>
        /// Gets or sets the line.
        /// </summary>
        /// <value>
        /// The line.
        /// </value>
        private int Line { get; set; }

        /// <summary>
        /// Gets or sets the col.
        /// </summary>
        /// <value>
        /// The col.
        /// </value>
        private int Col { get; set; }

        /// <summary>
        /// Reads the next char.
        /// </summary>
        /// <param name="skipWhitespaces">if set to <c>true</c> [skip whitespaces].</param>
        /// <returns>Next char</returns>
        public CharWithPosition ReadNextChar(bool skipWhitespaces)
        {
            char? currentChar = this.ReadNextChar();
            if (currentChar != null && currentChar.HasValue)
            {
                if (skipWhitespaces)
                {
                    while (char.IsWhiteSpace(currentChar.Value))
                    {
                        return this.ReadNextChar(skipWhitespaces);
                    }
                }

                CharWithPosition cwpChar = new CharWithPosition(currentChar.Value, this.Pos, this.Line, this.Col);
                this.charList.Add(cwpChar);
                return cwpChar;
            }
            else
            {
                CharWithPosition cwpChar = new CharWithPosition('\0', this.Pos, this.Line, this.Col);
                this.charList.Add(cwpChar);
                return cwpChar;
            }
        }

        /// <summary>
        /// Reverses the last char.
        /// </summary>
        public void ReverseLastChar()
        {
            CharWithPosition cwpChar = this.charList.Last<CharWithPosition>();
            this.charList.Remove(cwpChar);
            cwpChar = this.charList.Last<CharWithPosition>();
            this.Pos = cwpChar.Pos;
            this.Line = cwpChar.Line;
            this.Col = cwpChar.Col;
        }

        /// <summary>
        /// Reads the next char.
        /// </summary>
        /// <returns>Next char</returns>
        private char? ReadNextChar()
        {
            if (this.Pos < this.Text.Length)
            {
                char nextChar = this.Text[this.Pos];
                this.Pos++;
                if (nextChar == '\n')
                {
                    this.Line++;
                    this.Col = 0;
                }
                else
                {
                    this.Col++;
                }

                return nextChar;
            }
            else
            {
                return null;
            }
        }
    }
}
